/**
*  \file pwm_hw.c
*
*  \brief pwm driver function
*
*  \author dajin.li  <dajin.li@linde-china.cn>
*
*/

/*===============================================[ private includes  ]================================================*/
#include <xmc_gpio.h>
#include <xmc4500/io.h>
#include <xmc4500/processor.h>
#include <xmc4500/types_local.h>
#include "../sched/sched.h"
#include "../pal/pal_mem.h"

/*===============================================[ private defines   ]================================================*/

#define PWM_PERIOD          7500l
/*===============================================[ private variables ]================================================*/



/*================================================[ public functions ]================================================*/

//--------------------------------------------------------------
/// \brief pwm_hardware_init
/// Initialize pwm hardware
/// \return void
//--------------------------------------------------------------

void pwm_hardware_init(void)
{
    /*CUT-OFF_ISO_VALVE_OUT_LS_CPU_V P0.0 CCU80.OUT21*/
    XMC_GPIO_SetMode(P0_0, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT3);

    /*MAIN_CONTACTOR_OUT_LS_CPU_V P0.6 CCU80.OUT30*/
    XMC_GPIO_SetMode(P0_6, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT3);

    /*PWM initialization*/
    /*Global Idle Clear*/
    /*CS0I 0  CC80 IDLE mode clear*/
    /*CS0I 1  CC81 IDLE mode clear*/
    /*CS0I 2  CC82 IDLE mode clear*/
    /*CS0I 3  CC83 IDLE mode clear*/
    /*SPRB 8  Prescaler Run Bit Set*/
    CCU80->GIDLC = CCU8_GIDLC_CS0I_Msk | CCU8_GIDLC_CS1I_Msk | CCU8_GIDLC_CS2I_Msk | CCU8_GIDLC_CS3I_Msk;                      
    CCU80->GIDLC |= (1<<CCU8_GIDLC_SPRB_Pos);               
    
    /* Slice 80 */ 
    
    /*Prescaler Control*/
    /*PSIV [3:0]    Prescaler initial value, fccu8/8*/
    /*0    [31:4]   Reserved*/
    CCU80_CC80->PSC = 3;    
    
    /*Slice Timer Control*/
    /*TCM     0       Timer Counting Mode  1B Center aligned mode*/
    /*TSSM    1       Timer Single Shot Mode 0B Single shot mode is disabled*/
    /*CLST    2       Shadow Transfer on Clear*/
    /*CMOD    3       Capture Compare Mode 0B Compare Mode*/
    /*ECM     4       Extended Capture Mode 0B Normal Capture Mode.*/
    /*CAPC    [6:5]   Clear on Capture Control 00B Timer is never cleared on a capture event*/
    /*TLS     7       Timer Load selector 0B Timer is loaded with the value of CR1*/
    /*ENDM    [9:8]   Extended Stop Function Control 10B Clears the timer and run bit (flush/stop)*/
    /*STRM    10      Extended Start Function Control 1B Clears the timer and sets run bit, if not set(flush/start)*/
    /*SCE     11      Equal Capture Event enable*/
    /*CCS     12      Continuous Capture Enable*/
    /*DITHE   [14:13] Dither Enable*/
    /*DIM     15      Dither input selector*/
    /*FPE     16      Floating Prescaler enable*/
    /*TRAPE0  17      TRAP enable for CCU80.OUT00*/
    /*TRAPE1  18      TRAP enable for CCU80.OUT01*/
    /*TRAPE2  19      TRAP enable for CCU80.OUT02*/
    /*TRAPE3  20      TRAP enable for CCU80.OUT03*/
    /*TRPSE   21      TRAP Synchronization Enable 1B Exiting from TRAP state is synchronized with the PWM signal*/
    /*TRPSW   22      TRAP State Clear Control*/
    /*EMS     23      External Modulation Synchronization*/
    /*EMT     24      External Modulation Type*/
    /*MCME1   25      Multi Channel Mode Enable for Channel 1*/
    /*MCME2   26      Multi Channel Mode Enable for Channel 2*/
    /*EME     [28:27] External Modulation Channel enable*/
    /*STOS    [30:29] Status bit output selector*/
    /*0       31      Reserved*/    
    CCU80_CC80->TC = 0x00200601;

    /*Input Selector Configuration*/
    /*EV0IS    [3:0]     Event 0 signal selection 0111B CCU80.IN0H*/
    /*EV1IS    [7:4]     Event 1 signal selection*/
    /*EV2IS    [11:8]    Event 2 signal selection*/
    /*0        [15:12]   Reserved*/
    /*EV0EM    [17:16]   Event 0 Edge Selection 01B Signal active on rising edge*/
    /*EV1EM    [19:18]   Event 1 Edge Selection*/
    /*EV2EM    [21:20]   Event 2 Edge Selection*/
    /*EV0LM    22        Event 0 Level Selection 0B Active on HIGH level*/
    /*EV1LM    23        Event 1 Level Selection*/
    /*EV2LM    24        Event 2 Level Selection*/
    /*LPF0M    [26:25]   Event 0 Low Pass Filter Configuration, 00B LPF is disabled*/
    /*LPF1M    [28:27]   Event 1 Low Pass Filter Configuration*/
    /*LPF2M    [30:29]   Event 2 Low Pass Filter Configuration*/
    /*0        31        Reserved*/
    CCU80_CC80->INS = 0x00010007;                           // EV0IS = SCU.GSC80, rising

    /*Connection Matrix Control*/
    /*STRTS    [1:0]     External Start Functionality Selector 01B External Start Function triggered by Event 0*/
    /*ENDS     [3:2]     External Stop Functionality Selector 00B External Stop Function deactivated*/
    /*CAP0S    [5:4]     External Capture 0 Functionality Selector*/
    /*CAP1S    [7:6]     External Capture 1 Functionality Selector*/
    /*GATES    [9:8]     External Gate Functionality Selector*/
    /*UDS      [11:10]   External Up/Down Functionality Selector*/
    /*LDS      [13:12]   External Timer Load Functionality Selector*/
    /*CNTS     [15:14]   External Count Selector*/
    /*OFS      16        Override Function Selector*/
    /*TS       17        Trap Function Selector*/
    /*MOS      [19:18]   External Modulation Functionality Selector*/
    /*TCE      20        Timer Concatenation Enable*/
    /*0        [31:21]   Reserved*/    
    CCU80_CC80->CMC = 0x00000001;

    /*Channel Control*/
    /*ASE      0         Asymmetric PWM mode Enable, 0B Asymmetric PWM is disabled*/
    /*OCS1     1         Output selector for CCU80.OUT00, 0B CC80ST1 signal path is connected to the CCU80.OUT00*/
    /*OCS2     2         Output selector for CCU80.OUT01, 0B CC80ST1 inverted signal path is connected to the CCU80.OUT01*/
    /*OCS3     3         Output selector for CCU80.OUT02, 0B CC80ST2 signal path is connected to the CCU80.OUT02 */
    /*OCS4     4         Output selector for CCU80.OUT03, 0B CC80ST2 inverted signal path is connected to the CCU80.OUT03 */
    /*0        [31:5]    Reserved*/
    CCU80_CC80->CHC = 0x0;  
    
    /*Interrupt Enable Control*/
    /*PME      0         Period match while counting up enable 1B Period Match interrupt is enabled*/
    /*OME      1         One match while counting down enable, 1B One Match interrupt is enabled */
    /*CMU1E    2         Channel 1 Compare match while counting up enable*/
    /*CMD1E    3         Channel 1 Compare match while counting down enable*/
    /*CMU2E    4         Channel 2 Compare match while counting up enable*/
    /*CMD2E    5         Channel 2 Compare match while counting down enable*/
    /*E0AE     8         Event 0 interrupt enable*/
    /*E1AE     9         Event 1 interrupt enable*/
    /*E2AE     10        Event 2 interrupt enable*/
    CCU80_CC80->INTE = 0x0403;                              

    /*Service Request Selector*/
    /*POSR     [1:0]    Period/One match Service request selector, 11B Forward to CC80SR3*/
    /*CM1SR    [3:2]    Channel 1 Compare match Service request selector*/
    /*CM2SR    [5:4]    Channel 2 Compare match Service request selector*/
    /*E0SR     [9:8]    Event 0 Service request selector*/
    /*E1SR     [11:10]  Event 1 Service request selector*/
    /*E2SR     [13:12]  Event 2 Service request selector*/
    
    CCU80_CC80->SRS = 0x3;                                  

    /*Timer Shadow Period Value*/
    /*PRS      [15:0]   Period Register*/
    /* Period set = 120 MHz / 8 / (7500 * 2 * PSC) = 1 kHz*/
    CCU80_CC80->PRS = PWM_PERIOD - 1;       

    /*Channel 1 Compare Shadow Value*/
    /*CR1S     [15:0]   Shadow Compare Register for Channel 1*/
    CCU80_CC80->CR1S = 0;                                   


    /*Dead Time Control*/
    /*DTE1     0        Dead Time Enable for Channel 1*/
    /*DTE2     1        Dead Time Enable for Channel 2*/
    /*DCEN1    2        Dead Time Enable for CC80ST1*/
    /*DCEN2    3        Dead Time Enable for inverted CC80ST1*/
    /*DCEN3    4        Dead Time Enable for CC80ST2*/
    /*DCEN4    5        Dead Time Enable for inverted CC80ST2*/
    /*DTCC     [7:6]    Dead Time clock control, 00B ftclk*/
    CCU80_CC80->DTC = 0x00000000;

    /*Channel 1 Dead Time Values CC80ST1*/
    /*DT1R     [7:0]    Rise Value for Dead Time of Channel 1*/
    /*DT1F     [15:8]   Fall Value for Dead Time of Channel 1*/
    CCU80_CC80->DC1R = 0x00007878;  
    
    /*Channel 2 Dead Time Values CC80ST2*/
    /*DT2R     [7:0]    Rise Value for Dead Time of Channel 2*/
    /*DT2F     [15:8]   Fall Value for Dead Time of Channel 2*/
    
    CCU80_CC80->DC2R = 0x00007878;
    
    /*Channel 2 Compare Shadow Value*/
    CCU80_CC80->CR2S = 0;
    /*Global Channel Set*/
    /*S0SE      0       Slice 0 shadow transfer set enable*/
    CCU80->GCSS = CCU8_GCSS_S0SE_Msk;
    
    /* Slice 81*/

    CCU80_CC81->PSC = 3;                                    
    CCU80_CC81->TC = 0x00200601;
    CCU80_CC81->INS = 0x00010007;                           
    CCU80_CC81->CMC = 0x00000001;                           
    CCU80_CC81->CHC = 0x0;                                  
    CCU80_CC81->PRS = PWM_PERIOD - 1;                                   
    CCU80_CC81->CR1S = 0;
    CCU80_CC81->DTC = 0x00000000;
    CCU80_CC81->DC1R = 0x00007878;                          
    CCU80_CC81->DC2R = 0x00007878;
    CCU80_CC81->CR2S = 0; 
    CCU80->GCSS = CCU8_GCSS_S1SE_Msk;


    /* Slice 82*/

    CCU80_CC82->PSC = 3;                                    
    CCU80_CC82->TC = 0x00200601;
    CCU80_CC82->INS = 0x00010007;                           
    CCU80_CC82->CMC = 0x00000001;                           
    CCU80_CC82->CHC = 0x0;                                  
    CCU80_CC82->PRS = PWM_PERIOD - 1;                                   
    CCU80_CC82->CR1S = 0xFFFF;
    CCU80_CC82->DTC = 0x00000000;
    CCU80_CC82->DC1R = 0x00007878;                          
    CCU80_CC82->DC2R = 0x00007878;
    CCU80_CC82->CR2S = 0; 
    CCU80->GCSS = CCU8_GCSS_S2SE_Msk;


    /* Slice 83*/

    CCU80_CC83->PSC = 3;                                    
    CCU80_CC83->TC = 0x00200601;
    CCU80_CC83->INS = 0x00010007;                           
    CCU80_CC83->CMC = 0x00000001;                           
    CCU80_CC83->CHC = 0x0;                                  
    CCU80_CC83->PRS = PWM_PERIOD - 1;                                   
    CCU80_CC83->CR1S = 0xFFFF;
    CCU80_CC83->DTC = 0x00000000;
    CCU80_CC83->DC1R = 0x00007878;                          
    CCU80_CC83->DC2R = 0x00007878;
    CCU80_CC83->CR2S = 0; 
    CCU80->GCSS = CCU8_GCSS_S3SE_Msk;
    
    
    
    /*Passive Level Config*/
    /*PSL11    0     Output Passive Level for CCU80.OUT00  0B Passive Level is LOW*/
    /*PSL12    1     Output Passive Level for CCU80.OUT01*/
    /*PSL21    2     Output Passive Level for CCU80.OUT02*/
    /*PSL22    3     Output Passive Level for CCU80.OUT03*/
    
    CCU80_CC80->PSL = 0;
    /*Passive Level Config*/
    /*PSL11    0     Output Passive Level for CCU80.OUT10  0B Passive Level is LOW*/
    /*PSL12    1     Output Passive Level for CCU80.OUT11*/
    /*PSL21    2     Output Passive Level for CCU80.OUT12*/
    /*PSL22    3     Output Passive Level for CCU80.OUT13*/
    
    CCU80_CC81->PSL = 0;
    CCU80_CC82->PSL = 0;
    CCU80_CC83->PSL = 1;

    /*CCU Control Register*/
    /*GSC80     8        Global Start Control CCU80*/
    SCU_GENERAL->CCUCON |= (1 << SCU_GENERAL_CCUCON_GSC80_Pos);            
}
void set_main_cnt_duty(u16 duty)
{
    /*Channel 0, 1, CR1S*/
    /*Channel 2, 3, CR2S*/
    /*MAIN_CONTACTOR_OUT_LS_CPU_V P0.6 CCU80.OUT30*/
    CCU80_CC83->CR1S =  ((PWM_PERIOD * (u32)duty) >> 16) + 1;
    /*S3SE   12     w Slice 3 shadow transfer set enable*/
    CCU80->GCSS |= CCU8_GCSS_S3SE_Msk;
}
void set_iso_valve_duty(u16 duty)
{
    /*Channel 0, 1, CR1S*/
    /*Channel 2, 3, CR2S*/
    /*CUT-OFF_ISO_VALVE_OUT_LS_CPU_V P0.0 CCU80.OUT21*/
    CCU80_CC82->CR1S =  ((PWM_PERIOD * (u32)duty) >> 16) + 1;
    /*S2SE    8     w Slice 2 shadow transfer set enable*/
    CCU80->GCSS |= CCU8_GCSS_S2SE_Msk;
}



